package com.lingyun.financialmanagement.service.pojo;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lingyun.financialmanagement.dao.mapper.*;
import com.lingyun.financialmanagement.dao.pojo.*;
import com.lingyun.financialmanagement.service.ProjectService;
import com.lingyun.financialmanagement.utils.TokenGetUser;
import com.lingyun.financialmanagement.vo.ErrorCode;
import com.lingyun.financialmanagement.vo.Result;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

@Service
public class ProjectServiceImpl implements ProjectService {

    @Autowired
    private ProjectMapper projectMapper;

    @Autowired
    private ComponentPartMapper componentPartMapper;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private NumberTimeMapper numberTimeMapper;

    @Value("${redis.token.tokenAccountPrefix}")
    private String tokenAccountPrefix;
    @Autowired
    private UsersMapper usersMapper;
    @Autowired
    private BillMapper billMapper;
    @Autowired
    private OperationLogServiceImpl operationLogServiceImpl;

    @Override
    public Result selectAllProject() {
        QueryWrapper<Project> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("type", "project")
                .orderByAsc("(case state when '准备' then 0 when '进行中' then 1 when '结束' then 2 else 3 end)");
        List<Project> projects = projectMapper.selectList(queryWrapper);
        return Result.success(projects);
    }



    @Override
    public Result selectWarehouse() {
        QueryWrapper<Project> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("type", "warehouse");
        Project warehouse = projectMapper.selectOne(queryWrapper);
        return Result.success(warehouse);
    }

    @Override
    public Result selectProjectById(Integer id) {
        if (id == null){
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMsg());
        }
        // 获取用户id，然后通过用户id与项目id去获取次数表进行次数增加
        String token = request.getHeader("token");
        String account = redisTemplate.opsForValue().get(tokenAccountPrefix + token);
        if (account == null || account.isEmpty()) {
            return Result.fail(ErrorCode.TOKEN_ERROR.getCode(), ErrorCode.TOKEN_ERROR.getMsg());
        }
        Users users = usersMapper.selectByAccount(account);
        Project project = projectMapper.selectById(id);

        // 更新用户查询次数
        NumberTime numberTime = numberTimeMapper.selectByProjectAndUsers(users.getId(), project.getId());
        // 如果没有就新建一个
        if (numberTime == null) {
            numberTime = new NumberTime(null, project.getId(), users.getId(), 1);
            numberTimeMapper.insert(numberTime);
        }else {
            numberTime.setNumber(numberTime.getNumber() + 1);
            numberTimeMapper.updateById(numberTime);
        }
        return Result.success(project);
    }

    @Override
    public Result recommendProjectToken() {
        String token = request.getHeader("token");
        String account = redisTemplate.opsForValue().get(tokenAccountPrefix + token);
        if (account == null){
            return Result.fail(ErrorCode.TOKEN_ERROR.getCode(), ErrorCode.TOKEN_ERROR.getMsg());
        }
        Users users = usersMapper.selectByAccount(account);
        if (users == null){
            return Result.fail(ErrorCode.USERS_NULL.getCode(), ErrorCode.USERS_NULL.getMsg());
        }

        // 获取当前用户最高频使用次数
        QueryWrapper<NumberTime> numberTimeQueryWrapper = new QueryWrapper<>();
        numberTimeQueryWrapper.eq("users", users.getId());

        numberTimeQueryWrapper.orderByDesc("number");

        // 通过排序获取前三个
        Page<NumberTime> numberTimePage = new Page<>(1,3);
        numberTimePage = numberTimeMapper.selectPage(numberTimePage, numberTimeQueryWrapper);
        List<NumberTime> records = numberTimePage.getRecords();
        ArrayList<Project> projects = new ArrayList<>();

        // 将所有获取project放到数组中
        for (int i = 0; i < records.size(); i++) {
            Project project = projectMapper.selectById(records.get(i).getProject());
            if (project.getState().equals("进行中") || project.getState().equals("准备")){
                projects.add(project);
            }
        }
        return Result.success(projects);
    }

    @Override
    @Transactional
    public Result addProject(Project project) {
        // 验证唯一性
        project.setType("project");
        Project projectVerify = projectMapper.selectByName(project.getName());
        if (projectVerify != null){
            return Result.fail(ErrorCode.NAME_UNIQUE.getCode(), ErrorCode.NAME_UNIQUE.getMsg());
        }
        // 获取账号 设置操作用户
        Result usersResult = TokenGetUser.getUsers(request, redisTemplate, tokenAccountPrefix, usersMapper);
        if (usersResult.getCode() != 200){
            return usersResult;
        }
        Users users = (Users) usersResult.getData();

        // 设置用户
        project.setUsers(users.getId());

        Integer billId = project.getBill();
        Bill bill = billMapper.selectById(billId);

        // 如果税率不为0则计算税额
        if (!bill.getTaxRate().equals(new BigDecimal(0))){
            // 这是原本公式
//            Float tax = project.getInvestmentAmount() - project.getInvestmentAmount() / (1 + bill.getTaxRate());
            BigDecimal tax = project.getInvestmentAmount().subtract(project.getInvestmentAmount().divide(bill.getTaxRate().add(new BigDecimal(1)), 2, BigDecimal.ROUND_HALF_UP));
            project.setInvestmentAmountTax(tax);
        }

        // 插入项目
        int insert = 0;
        try{
            insert = projectMapper.insert(project);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.fail(ErrorCode.INSERT_ERROR.getCode(), ErrorCode.INSERT_ERROR.getMsg());
        }
        if (insert == 0){
            return Result.fail(ErrorCode.INSERT_ERROR.getCode(), ErrorCode.INSERT_ERROR.getMsg());
        }

        // 增加日志
        Result result = operationLogServiceImpl.insertLog(request, new OperationLog(null, null, null, null, project.getId(), "增加了项目", null));
        if (result.getCode() != 200){
            throw new RuntimeException(result.getMsg());
        }
        return Result.success(project);
    }

    @Override
    public Result selectAllProjectAndWarehouse() {
        QueryWrapper<Project> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("type", "project").or().eq("type", "warehouse");
        List<Project> projects = projectMapper.selectList(queryWrapper);
        return Result.success(projects);
    }

    @Override
    @Transactional
    public Result addProjectWareHouse(Integer id, Integer type, Float cost) {
        Project project = projectMapper.selectById(id);
        // 公户收款
        if (type == 1){
            project.setPublicCollect(project.getPublicCollect().add(BigDecimal.valueOf(cost)));
        }
        // 现金收款
        else if (type == 2){
            project.setCashCollect(project.getCashCollect().add(BigDecimal.valueOf(cost)));
        }
        try{
            projectMapper.updateById(project);
        }catch (Exception e){
            return Result.fail(ErrorCode.UPDATE_ERROR.getCode(), ErrorCode.UPDATE_ERROR.getMsg());
        }

        Result result = operationLogServiceImpl.insertLog(request, new OperationLog(null, null, null, null, id, "项目收款" + cost + "￥", null));
        if (result.getCode() != 200){
            throw new RuntimeException(result.getMsg());
        }
        return Result.success(project);
    }

    // 注资
    @Override
    @Transactional
    public Result assetInject(Project project) {
        // 设置类型
        project.setType("asset_inject");

        // 获取账号 设置操作用户
        Result usersResult = TokenGetUser.getUsers(request, redisTemplate, tokenAccountPrefix, usersMapper);
        if (usersResult.getCode() != 200){
            return usersResult;
        }
        Users users = (Users) usersResult.getData();

        // 设置用户
        project.setUsers(users.getId());
        // 设置注入标题
        project.setName(users.getName() + "资产注入" + System.currentTimeMillis());
        // 设置项目进度
        project.setState("结束");

        Integer billId = project.getBill();
        Bill bill = billMapper.selectById(billId);

        // 如果税率不为0则 计算税额
        if (!bill.getTaxRate().equals(new BigDecimal(0))){

//            Float tax = project.getInvestmentAmount() - project.getInvestmentAmount() / (1 + bill.getTaxRate());
            BigDecimal tax = project.getInvestmentAmount().subtract(project.getInvestmentAmount().divide(bill.getTaxRate().add(new BigDecimal(1)), 2, BigDecimal.ROUND_HALF_UP));
            project.setInvestmentAmountTax(tax);
        }

        // 插入项目
        int insert = 0;
        try{
            insert = projectMapper.insert(project);
        } catch (Exception e) {
            return Result.fail(ErrorCode.INSERT_ERROR.getCode(), ErrorCode.INSERT_ERROR.getMsg());
        }
        if (insert == 0){
            return Result.fail(ErrorCode.INSERT_ERROR.getCode(), ErrorCode.INSERT_ERROR.getMsg());
        }

        if (project.getPublicCollect() == null){
            project.setPublicCollect(BigDecimal.valueOf(0));
        }

        if (project.getCashCollect() == null){
            project.setCashCost(BigDecimal.valueOf(0));
        }

        System.out.println(project.getPublicCollect());
        System.out.println(project.getCashCollect());
        // 记录日志
        Result result = operationLogServiceImpl.insertLog(request, new OperationLog(null, null, null, null, null, "注入了资金" + (project.getPublicCollect().add(project.getCashCollect())) + " ￥", null));
        if (result.getCode() != 200){
            throw new RuntimeException(result.getMsg());
        }

        return Result.success(project);
    }

    @Override
    public Result loan(Project project) {
        // 设置类型
        project.setType("loan");

        // 获取账号 设置操作用户
        Result usersResult = TokenGetUser.getUsers(request, redisTemplate, tokenAccountPrefix, usersMapper);
        if (usersResult.getCode() != 200){
            return usersResult;
        }
        Users users = (Users) usersResult.getData();
        // 设置用户
        project.setUsers(users.getId());

        // 设置注入标题
        project.setName(users.getName() + "借贷" + System.currentTimeMillis());

        // 设置项目进度
        project.setState("进行中");

        // 查找税率为0的发票
        Bill bill = billMapper.selectByTaxRate(0F);
        // 加上
        project.setBill(bill.getId());

        // 设置借贷值
        project.setCredit(project.getInvestmentAmount());

        // 插入项目
        int insert = 0;
        try{
            insert = projectMapper.insert(project);
        } catch (Exception e) {
            return Result.fail(ErrorCode.INSERT_ERROR.getCode(), ErrorCode.INSERT_ERROR.getMsg());
        }
        if (insert == 0){
            return Result.fail(ErrorCode.INSERT_ERROR.getCode(), ErrorCode.INSERT_ERROR.getMsg());
        }

        ComponentPart componentPart = new ComponentPart(null, project.getId() + "借贷" + System.currentTimeMillis(), "借贷", 1, project.getInvestmentAmount(), project.getInvestmentAmount(), project.getBill(), users.getId(), "公司赊销", null, project.getId(),null, null, null, null, users.getId(), null, null);
        componentPartMapper.insert(componentPart);

        // 记录日志
        Result result = operationLogServiceImpl.insertLog(request, new OperationLog(null, null, null, null, null, "借贷资金" + project.getCredit() + "￥", null));
        if (result.getCode() != 200){
            throw new RuntimeException(result.getMsg());
        }

        return Result.success(project);
    }

    @Override
    @Transactional
    public Result updateStateProject(Integer id, String state) {
        if (state == null || !(state.equals("结束") || state.equals("准备") || state.equals("进行中"))){
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMsg());
        }
        Project project = projectMapper.selectById(id);
        project.setState(state);
        int update = 0;
        try{
            update = projectMapper.updateById(project);
        } catch (Exception e) {
            return Result.fail(ErrorCode.UPDATE_ERROR.getCode(), ErrorCode.UPDATE_ERROR.getMsg());
        }
        if (update == 0){
            return Result.fail(ErrorCode.UPDATE_ERROR.getCode(), ErrorCode.UPDATE_ERROR.getMsg());
        }

        // 日志记录
        Result result = operationLogServiceImpl.insertLog(request, new OperationLog(null, null, null, null, id, "更改项目状态为：" + state, null));
        if (result.getCode() != 200){
            throw new RuntimeException(result.getMsg());
        }
        return Result.success(project);
    }

    @Override
    public Result deleteProjectById(Integer id) {
        QueryWrapper<ComponentPart> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("project", id);
        List<ComponentPart> componentParts = componentPartMapper.selectList(queryWrapper);
        if (!componentParts.isEmpty()){
            return Result.fail(ErrorCode.PROJECT_DELETE_ERROR.getCode(), ErrorCode.PROJECT_DELETE_ERROR.getMsg());
        }
        int delete = 0;
        try{
            delete = projectMapper.deleteById(id);
        } catch (Exception e) {
            return Result.fail(ErrorCode.PROJECT_DELETE_ERROR.getCode(), ErrorCode.PROJECT_DELETE_ERROR.getMsg());
        }
        if (delete == 0){
            return Result.fail(ErrorCode.PROJECT_DELETE_ERROR.getCode(), ErrorCode.PROJECT_DELETE_ERROR.getMsg());
        }

        return Result.success(true);
    }
}
